<?php
//   +----------------------------------------------------------------------
//   | Copyright (c) 2015-2025 http://www.hdphp.cn All rights reserved.
//   | Licensed ( http://www.hdphp.cn/licenses/ )
//   | Author: Jack <sophia2152@qq.com>
//   | 官方网址: http://www.hdphp.cn
//   | 这不是一个自由软件！您只能在不用于商业目的的前提下对程序代码进行修改和使用。
//   | 任何企业和个人不允许对程序代码以任何形式任何目的再发布。
//   +----------------------------------------------------------------------
namespace hdphp\services\wechat\orderShipping;

use hdphp\exceptions\AdminException;
use hdphp\services\wechat\config\PaymentConfig;
use think\facade\Cache;

/**
 * Class：OrderClient
 * 创建人：Jack
 * 创建时间：2023/11/30 14:40
 * @package hdphp\services\wechat\orderShipping
 */
class OrderClient extends BaseClient
{
    const redis_prefix = 'mini_order';

    const express_company = 'ZTO';   // 默认发货快递公司为（中通快递）

    /**
     * @var \Redis
     */
    protected $redis;

    /**
     * 注释：getRedis
     * 创建人：Jack
     * 创建时间：2023/11/30 14:41
     * @return object|\Redis|null
     */
    protected function getRedis()
    {
        if (empty($this->redis)) {
            $this->redis = Cache::store('redis')->handler();
        }
        return $this->redis;
    }

    /**
     * 注释：处理联系人
     * 创建人：Jack
     * 创建时间：2023/11/30 14:46
     * @param array $contact
     * @return array
     */
    protected function handleContact(array $contact = []): array
    {
        if (isset($contact)) {
            if (isset($contact['consignor_contact']) && $contact['consignor_contact']) {
                $contact['consignor_contact'] = Utility::encryptTel($contact['consignor_contact']);
            }
            if (isset($contact['receiver_contact']) && $contact['receiver_contact']) {
                $contact['receiver_contact'] = Utility::encryptTel($contact['receiver_contact']);
            }
        }
        return $contact;
    }

    /**
     * 注释：发货
     * 创建人：Jack
     * 创建时间：2023/11/30 14:47
     * @param string $out_trade_no
     * @param int    $logistics_type
     * @param array  $shipping_list
     * @param string $payer_openid
     * @param        $path
     * @param int    $delivery_mode
     * @param bool   $is_all_delivered
     * @return array
     */
    public function shippingByTradeNo(string $out_trade_no, int $logistics_type, array $shipping_list, string $payer_openid, $path, int $delivery_mode = 1, bool $is_all_delivered = true)
    {
        if (!$this->checkManaged()) {
            throw new AdminException('开通小程序订单管理服务后重试!');
        }
        /** @var PaymentConfig $make */
        $make = app()->make(PaymentConfig::class);
        $params = [
            'order_key' => [
                'order_number_type' => 2,
                'mchid' => $make->get('mchId'),
                //                'out_trade_no' => $out_trade_no,
                'transaction_id' => $out_trade_no
            ],
            'logistics_type' => $logistics_type,
            'delivery_mode' => $delivery_mode,
            'upload_time' => date(DATE_RFC3339),
            'payer' => [
                'openid' => $payer_openid
            ]
        ];
        if ($delivery_mode == 2) {
            $params['is_all_delivered'] = $is_all_delivered;
        }

        foreach ($shipping_list as $shipping) {
            $contact = $this->handleContact($shipping['contact'] ?? []);
            $params['shipping_list'][] = [
                'tracking_no' => $shipping['tracking_no'] ?? '',
                'express_company' => isset($shipping['express_company']) ? $this->getDelivery($shipping['express_company']) : '',
                'item_desc' => $shipping['item_desc'],
                'contact' => $contact
            ];
        }
        // 跳转路径
//        $this->setMesJumpPath($path);
        return $this->shipping($params);
    }

    /**
     * 注释：合单
     * 创建人：Jack
     * 创建时间：2023/11/30 14:47
     * @param string $out_trade_no
     * @param int    $logistics_type
     * @param array  $sub_orders
     * @param string $payer_openid
     * @param int    $delivery_mode
     * @param bool   $is_all_delivered
     * @return array
     */
    public function combinedShippingByTradeNo(string $out_trade_no, int $logistics_type, array $sub_orders, string $payer_openid, int $delivery_mode = 2, bool $is_all_delivered = false)
    {
        if (!$this->checkManaged()) {
            throw new AdminException('开通小程序订单管理服务后重试');
        }
        $params = [
            'order_key' => [
                'order_number_type' => 1,
                'mchid' => $this->config['config']['mini_program']['merchant_id'],
                'out_trade_no' => $out_trade_no,
            ],
            'upload_time' => date(DATE_RFC3339),
            'payer' => [
                'openid' => $payer_openid
            ]
        ];

        foreach ($sub_orders as $order) {
            $sub_order = [
                'order_key' => [
                    'order_number_type' => 1,
                    'mchid' => $this->config['config']['mini_program']['merchant_id'],
                    'out_trade_no' => $order['out_trade_no'],
                    'logistics_type' => $logistics_type,
                ],
                'delivery_mode' => $delivery_mode,
                'is_all_delivered' => $is_all_delivered
            ];
            foreach ($sub_orders['shipping_list'] as $shipping) {
                $contact = $this->handleContact($shipping['contact'] ?? []);
                $sub_order['shipping_list'][] = [
                    'tracking_no' => $shipping['tracking_no'] ?? '',
                    'express_company' => isset($shipping['express_company']) ? $this->getDelivery($shipping['express_company']) : '',
                    'item_desc' => $shipping['item_desc'],
                    'contact' => $contact
                ];
            }
            $params['sub_orders'][] = $sub_order;
        }

        return $this->combinedShipping($params);
    }

    /**
     * 注释：签收通知
     * 创建人：Jack
     * 创建时间：2023/11/30 14:48
     * @param string $merchant_trade_no
     * @param string $received_time
     * @return array
     */
    public function notifyConfirmByTradeNo(string $merchant_trade_no, string $received_time)
    {
        $params = [
            'merchant_id' => $this->config['config']['mini_program']['merchant_id'],
            'merchant_trade_no' => $merchant_trade_no,
            'received_time' => $received_time
        ];
        return $this->notifyConfirm($params);
    }

    /**
     * 注释：设置跳转连接
     * 创建人：Jack
     * 创建时间：2023/11/30 14:48
     * @param $path
     * @return array
     */
    public function setMesJumpPathAndCheck($path)
    {
        if (!$this->checkManaged()) {
            throw new AdminException('开通小程序订单管理服务后重试!');
        }
        return $this->setMesJumpPath($path);
    }

    /**
     * 注释：设置小程序管理服务开通状态
     * 创建人：Jack
     * 创建时间：2023/11/30 14:48
     * @return bool
     */
    public function setManaged()
    {
        try {
            $res = $this->isManaged();
            if ($res['is_trade_managed']) {
                $key = self::redis_prefix . '_is_trade_managed';
                $this->getRedis()->set($key, $res['is_trade_managed']);
                return true;
            } else {
                return false;
            }
        } catch (\Throwable $e) {
            return false;
        }
    }

    /**
     * 注释：checkManaged
     * 创建人：Jack
     * 创建时间：2023/11/30 14:48
     * @return bool
     * @throws \RedisException
     */
    public function checkManaged()
    {
        $key = self::redis_prefix . '_is_trade_managed';
        if ($this->getRedis()->exists($key)) {
            return true;
        } else {
            return $this->setManaged();
        }
    }

    /**
     * 注释：同步去微信物流列表
     * 创建人：Jack
     * 创建时间：2023/11/30 14:48
     * @return array
     * @throws \RedisException
     */
    public function setDeliveryList()
    {
        $list = $this->getDeliveryList();
        if ($list) {
            $key = self::redis_prefix . '_delivery_list';
            $date = array_column($list['delivery_list'], 'delivery_id', 'delivery_name');
            // 创建缓存
            $this->getRedis()->hMSet($key, $date);

            return $date;
        } else {
            throw new AdminException('物流公司列表异常!');
        }
    }

    /**
     * 注释：获取物流公司编码
     * 创建人：Jack
     * 创建时间：2023/11/30 14:48
     * @param $company_name
     * @return mixed|string
     * @throws \RedisException
     */
    public function getDelivery($company_name)
    {
        $key = self::redis_prefix . '_delivery_list';
        if (!$this->getRedis()->exists($key)) {
            $date = $this->setDeliveryList();
            $express_company = $date[$company_name] ?? '';
        } else {
            $express_company = $this->getRedis()->hMGet($key, [$company_name])[$company_name] ?? '';
        }
        if (empty($express_company)) {
            $express_company = self::express_company;
        }

        return $express_company;
    }
}